

import React, { useMemo, CSSProperties, AnimationEventHandler } from 'react';
import styled, { css, keyframes } from 'styled-components';

type AnimationDirection = 'clockwise' | 'counterclockwise'
type AnimationStartPosition = 'left' | 'right' | 'top' | 'bottom';
type Angle = {
  start: number;
  end: number;
};
interface RotatingDotProps {
  $direction: AnimationDirection;
  $positon: AnimationStartPosition;
  $angle?: Angle
  $second: number;
  $size: number;
  $repeat: number | boolean;
  radius: number; // Rotate radius
  $isAnimating: boolean; // Whether to apply the animation
  $isEnd?: boolean; // animation is end
}

// Define the keyframes for circular motion
const Position = {
  clockwise: {
    bottom: {
      start: { s: 0, e: 0 },
      end: { s: 360, e: -360 }
    },
    top: {
      start: { s: 180, e: -180 },
      end: { s: 540, e: -540 }
    },
    left: {
      start: { s: 90, e: -90, },
      end: { s: 450, e: -450 }
    },
    right: {
      start: { s: 270, e: -270 },
      end: { s: 630, e: -630 }
    }
  },
  counterclockwise: {
    bottom: {
      start: { s: 0, e: 0 },
      end: { s: -360, e: 360 }
    },
    top: {
      start: { s: -180, e: 180 },
      end: { s: -540, e: 540 }
    },
    right: {
      start: { s: -90, e: 90, },
      end: { s: -450, e: 450 }
    },
    left: {
      start: { s: -270, e: 270 },
      end: { s: -630, e: 630 }
    }
  }
}

const StartPosition = {
  h: {
    top: 0,
    left: -1,
    bottom: 0,
    right: 1
  },
  v: {
    top: -1,
    left: 0,
    bottom: 1,
    right: 0
  }
}

const angle = (positon: AnimationStartPosition, direction: AnimationDirection, angle?: { start: number, end: number }): { start: { s: number, e: number }; end: { s: number, e: number } } => {
  if (!angle) {
    return {
      start: { s: Position[direction][positon].start.s, e: Position[direction][positon].start.e },
      end: { s: Position[direction][positon].end.s, e: Position[direction][positon].end.e }
    }
  }

  const flag = direction === 'clockwise' ? [1, -1] : [-1, 1]

  return {
    start: { s: angle.start * flag[0], e: angle.start * flag[0] },
    end: { s: angle.end * flag[0], e: angle.end * flag[0] }
  }
}

const rotateAround = (radius: number, positon: AnimationStartPosition, direction: AnimationDirection, angleInfo?: Angle) => {
  const info = angle(positon, direction, angleInfo)
  return keyframes`
  from {
    transform: rotate(${info.start.s}deg) translateY(${radius}px) rotate(${info.start.e}deg);
  }
  to {
    transform: rotate(${info.end.s}deg) translateY(${radius}px) rotate(${info.end.e}deg);
  }
`
};

// Styled component for the fixed center dot
// const CenterDot = styled.div`
//   width: 20px;
//   height: 20px;
//   background-color: #333;
//   border-radius: 50%;
//   position: absolute;
//   top: 50%;
//   left: 50%;
//   transform: translate(-50%, -50%);
// `;

// Styled component for the rotating dot
const RotatingDot = styled.div<RotatingDotProps>`
  width: ${({ $size }) => `${$size}px`};
  height: ${({ $size }) => `${$size}px`};
  position: absolute;
  top: ${({ $size, radius, $positon }) => `calc(50% - ${$size / 2}px + ${StartPosition['v'][$positon] * radius}px)`};
  left: ${({ $size, radius, $positon }) => `calc(50% - ${$size / 2}px + ${StartPosition['h'][$positon] * radius}px)`};
  ${({ radius, $isAnimating, $second, $positon, $direction, $size, $angle, $repeat }) =>
    $isAnimating &&
    css`
      animation: ${rotateAround(radius, $positon, $direction, $angle)} ${$second}s linear forwards ${typeof $repeat === 'number' ? $repeat : ($repeat ? 'infinite' : 1)};
      top: calc(50% - ${$size / 2}px);
      left: calc(50% - ${$size / 2}px);
    `}
`;

const Orbit = styled.div<{ $size: number }>`
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border: 1px solid red;
    border-radius: 50%;
    width: ${({ $size }) => `${$size}px`};
    height: ${({ $size }) => `${$size}px`};
`

const Text = styled.div<{ $size: number, $radius: number }>`
  box-sizing: border-box;
  width: 100%;
  margin-top: ${({ $size, $radius }) => `calc(50% + ${$size / 2}px + ${$radius}px)`};
`

interface AnimationCycleProps {
  direction?: AnimationDirection;
  position?: AnimationStartPosition;
  angle?: {
    start: number;
    end: number;
  }
  repeat?: boolean | number;
  radius: number;
  isAnimating: boolean;
  second: number;
  className?: string;
  dot: {
    style?: CSSProperties;
    size: number;
    className?: string;
    element?: React.ReactNode;
  };
  text?: React.ReactNode;
  showOrbit?: boolean;
  onAnimationIteration?: AnimationEventHandler<HTMLDivElement> | undefined;
}

const AnimationCycle: React.FC<AnimationCycleProps> = ({ radius = 100, repeat = true, isAnimating, dot, showOrbit, second, position, direction, className, text, angle, onAnimationIteration }) => {
  const animation = useMemo(() => isAnimating, [isAnimating])
  return (
    <div
      id='animation'
      className={className}
      style={{ position: 'relative', width: '100%', height: '100%' }}
    >
      {/* <CenterDot /> */}
      <RotatingDot
        onAnimationEnd={onAnimationIteration}
        onAnimationIteration={onAnimationIteration}
        className={dot.className}
        style={dot.style}
        radius={radius}
        $isAnimating={animation}
        $size={dot.size}
        $repeat={repeat}
        $second={second}
        $direction={direction || 'clockwise'}
        $positon={position || 'right'}
        $angle={angle}
      >
        {dot.element}
      </RotatingDot>
      {text && <Text
        $size={dot.size}
        $radius={radius}
      >{text}</Text>}
      {showOrbit && <Orbit $size={radius * 2} />}
    </div>
  );
};

export default AnimationCycle;
